package com.tsfyun.scm.service.impl.customer;

import cn.hutool.core.collection.CollectionUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.tsfyun.common.base.config.OrikaBeanMapper;
import com.tsfyun.common.base.enums.ResultCodeEnum;
import com.tsfyun.common.base.exception.ServiceException;
import com.tsfyun.common.base.extension.OrderItem;
import com.tsfyun.common.base.extension.ServiceImpl;
import com.tsfyun.common.base.security.SecurityUtil;
import com.tsfyun.common.base.util.StringUtils;
import com.tsfyun.common.base.util.TsfPreconditions;
import com.tsfyun.scm.dto.customer.SupplierDTO;
import com.tsfyun.scm.dto.customer.SupplierPlusInfoDTO;
import com.tsfyun.scm.dto.customer.SupplierQTO;
import com.tsfyun.scm.dto.customer.client.ClientSupplierDTO;
import com.tsfyun.scm.dto.customer.client.ClientSupplierQTO;
import com.tsfyun.scm.entity.customer.Customer;
import com.tsfyun.scm.entity.customer.Supplier;
import com.tsfyun.scm.entity.customer.SupplierTakeInfo;
import com.tsfyun.scm.mapper.customer.SupplierMapper;
import com.tsfyun.scm.service.customer.ICustomerService;
import com.tsfyun.scm.service.customer.ISupplierBankService;
import com.tsfyun.scm.service.customer.ISupplierService;
import com.tsfyun.scm.service.customer.ISupplierTakeInfoService;
import com.tsfyun.scm.service.file.IUploadFileService;
import com.tsfyun.scm.util.PermissionUtil;
import com.tsfyun.scm.util.TsfWeekendSqls;
import com.tsfyun.scm.vo.customer.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.weekend.WeekendSqls;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  供应商服务实现类
 * </p>
 *

 * @since 2020-03-12
 */
@Service
public class SupplierServiceImpl extends ServiceImpl<Supplier> implements ISupplierService {

    @Autowired
    private ICustomerService customerService;

    @Autowired
    private ISupplierTakeInfoService supplierTakeInfoService;

    @Autowired
    private ISupplierBankService supplierBankService;

    @Autowired
    private OrikaBeanMapper beanMapper;

    @Autowired
    private SupplierMapper supplierMapper;

    @Autowired
    private IUploadFileService uploadFileService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long addPlus(SupplierPlusInfoDTO dto) {
        SupplierDTO supplierDTO = dto.getSupplier();
        //保存供应商信息
        Supplier supplier = simpleAdd(supplierDTO);
        //批量保存供应商银行信息
        supplierBankService.addBatch(supplier.getId(),dto.getBanks());
        //批量保存供应商提货信息
        supplierTakeInfoService.addBatch(supplier.getId(),dto.getTakes());
        //关联文件信息
        uploadFileService.relateFile(supplier.getId().toString(),dto.getFile());
        return supplier.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void editPlus(SupplierPlusInfoDTO dto) {
        SupplierDTO supplierDTO = dto.getSupplier();
        //修改供应商信息
        simpleEdit(supplierDTO);
        //删除供应商提货信息
        supplierTakeInfoService.removeBySupplierId(supplierDTO.getId());
        //批量保存供应商提货信息
        supplierTakeInfoService.addBatch(supplierDTO.getId(),dto.getTakes());
        //删除供应商银行信息
        supplierBankService.removeBySupplierId(supplierDTO.getId());
        //批量保存供应商银行信息
        supplierBankService.addBatch(supplierDTO.getId(),dto.getBanks());
    }

    @Override
    public SupplierPlusVO detailPlus(Long id) {
        Supplier supplier = super.getById(id);
        TsfPreconditions.checkArgument(Objects.nonNull(supplier),new ServiceException("供应商信息不存在"));
        SupplierPlusVO supplierPlusVO = new SupplierPlusVO(beanMapper.map(supplier, SupplierVO.class));
        //获取客户信息
        Customer customer = customerService.getById(supplier.getCustomerId());
        Optional.ofNullable(customer).ifPresent(r->{
            supplierPlusVO.getSupplier().setCustomerName(r.getName());
        });
        //获取供应商提货信息
        List<SupplierTakeInfo> takes =  supplierTakeInfoService.list(id);
        if(CollectionUtil.isNotEmpty(takes)) {
            //先按是否默认排序，然后再按修改日期排序
            takes = takes.stream().sorted(Comparator.comparing(SupplierTakeInfo::getIsDefault).thenComparing(SupplierTakeInfo::getDateUpdated).reversed())
                    .collect(Collectors.toList());
            supplierPlusVO.setTakes(beanMapper.mapAsList(takes, SupplierTakeInfoVO.class));
        }

        //获取供应商银行信息
        supplierPlusVO.setBanks(supplierBankService.listBySupplierId(id));
        return supplierPlusVO;
    }

    @Override
    public SupplierVO detail(Long id) {
        Supplier supplier = super.getById(id);
        TsfPreconditions.checkArgument(Objects.nonNull(supplier),new ServiceException("供应商信息不存在"));
        return beanMapper.map(supplier, SupplierVO.class);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateDisabled(Long id, Boolean disabled) {
        Supplier supplier = super.getById(id);
        TsfPreconditions.checkArgument(Objects.nonNull(supplier),new ServiceException("供应商信息不存在"));
        Supplier update = new Supplier();
        update.setDisabled(disabled);
        supplierMapper.updateByExampleSelective(update, Example.builder(Supplier.class).where(
                WeekendSqls.<Supplier>custom().andEqualTo(Supplier::getId,id)
        ).build());
    }

    @Override
    public List<SimpleSupplierVO> select(Long customerId) {
        List<Supplier> suppliers =  super.list(new Supplier().setCustomerId(customerId).setDisabled(Boolean.FALSE));
        //按修改时间排序
        suppliers = suppliers.stream().sorted(Comparator.comparing(Supplier::getDateUpdated).reversed()).collect(Collectors.toList());
        return beanMapper.mapAsList(suppliers,SimpleSupplierVO.class);
    }

    @Override
    public List<SimpleSupplierVO> vague(String customerName, String name) {
        if(StringUtils.isEmpty(customerName)){
            return Lists.newArrayList();
        }
        return supplierMapper.vague(new LinkedHashMap<String, Object>(){{
            put("customerName",customerName);
            put("name",name);
        }});
    }

    @Override
    public List<SimpleSupplierVO> clientVague(String name) {
        return supplierMapper.clientVague(SecurityUtil.getCurrentCustomerId(),name);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Supplier simpleAdd(SupplierDTO dto) {
        dto.setName(StringUtils.removeSpecialSymbol(dto.getName()));
        dto.setAddress(StringUtils.removeSpecialSymbol(dto.getAddress()));
        Supplier supplier = beanMapper.map(dto,Supplier.class);
        //校验客户信息是否存在
        Customer customer = customerService.findByName(dto.getCustomerName());
        TsfPreconditions.checkArgument(Objects.nonNull(customer),new ServiceException("您选择的客户不存在"));
        supplier.setCustomerId(customer.getId());
        //检查该客户是否存在同名的供应商
        Supplier condition = new Supplier().setName(dto.getName()).setCustomerId(customer.getId());
        TsfPreconditions.checkArgument( super.count(condition) < 1,new ServiceException(String.format("客户：%s  已经存在名称为：%s  的供应商",customer.getName(),dto.getName())));
        supplier.setDisabled(Boolean.FALSE);
        //保存供应商信息
        super.saveNonNull(supplier);
        return supplier;
    }

    @Override
    public Supplier findByCustomerNameAndSupplierName(String customerName, String supplierName) {
        Map<String,Object> params = new LinkedHashMap<String,Object>(){{
           put("customerName",customerName);
           put("supplierName",supplierName);
        }};
        return supplierMapper.findByCustomerNameAndSupplierName(params);
    }

    @Override
    public Supplier findByCustomerIdAndSupplierName(Long customerId, String supplierName) {
        return supplierMapper.findByCustomerIdAndSupplierName(customerId,supplierName);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void simpleEdit(SupplierDTO dto) {
        //校验供应商信息是否存在
        Supplier supplier = super.getById(dto.getId());
        TsfPreconditions.checkArgument(Objects.nonNull(supplier),new ServiceException("供应商信息不存在"));
        //校验客户信息是否存在
        Customer customer = customerService.findByName(dto.getCustomerName());
        TsfPreconditions.checkArgument(Objects.nonNull(customer),new ServiceException("您选择的客户不存在"));
        //校验该客户是否存在同名的供应商
        supplier.setName(StringUtils.removeSpecialSymbol(dto.getName()));

        int count = supplierMapper.selectCountByExample(Example.builder(Supplier.class).where(WeekendSqls.<Supplier>custom()
                    .andEqualTo(Supplier::getCustomerId, customer.getId())
                    .andEqualTo(Supplier::getName,supplier.getName())
                    .andNotEqualTo(Supplier::getId,supplier.getId())).build());
        TsfPreconditions.checkArgument(count < 1,new ServiceException(String.format("客户：%s  已经存在名称为：%s  的供应商",customer.getName(),supplier.getName())));
        supplier.setCustomerId(customer.getId());
        supplier.setAddress(StringUtils.removeSpecialSymbol(dto.getAddress()));
        super.updateById(supplier);
    }

    @Override
    public PageInfo<SupplierVO> pageList(SupplierQTO qto) {
        PageHelper.startPage(qto.getPage(),qto.getLimit());
        Map<String,Object> params = beanMapper.map(qto,Map.class);
        return new PageInfo<>(supplierMapper.list(params));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void remove(Long id) {
        //如果供应商下面有提货信息和银行信息，暂不允许删除，以免误删
        int supplierTakeInfoCount = supplierTakeInfoService.countBySupplierId(id);
        TsfPreconditions.checkArgument(supplierTakeInfoCount < 1,new ServiceException(String.format("该供应商下面存在%d条提货信息，不允许删除",supplierTakeInfoCount)));
        int supplierBankCount = supplierBankService.countBySupplierId(id);
        TsfPreconditions.checkArgument(supplierTakeInfoCount < 1,new ServiceException(String.format("该供应商下面存在%d条银行信息，不允许删除",supplierBankCount)));
        try {
            super.removeById(id);
        } catch (DataIntegrityViolationException e) {
            throw new ServiceException("当前供应商数据已被使用，禁止删除");
        }
    }

    @Override
    public int countByCustomerId(Long customerId) {
        return supplierMapper.selectCountByExample(Example.builder(Supplier.class).where(TsfWeekendSqls.<Supplier>custom().andEqualTo(true,Supplier::getCustomerId,customerId)).build());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long clientAdd(ClientSupplierDTO dto) {
        Customer customer = customerService.getById(SecurityUtil.getCurrentCustomerId());
        if(Objects.isNull(customer)) {
            throw new ServiceException(ResultCodeEnum.CUSTOMER_NO_EXISTS_ERROR);
        }
        Supplier supplier = new Supplier();
        supplier.setCustomerId(customer.getId());
        //检查该客户是否存在同名的供应商
        Supplier condition = new Supplier().setName(dto.getName()).setCustomerId(customer.getId());
        TsfPreconditions.checkArgument( super.count(condition) < 1,new ServiceException(String.format("已经存在名称为：%s  的供应商，请勿重复添加",dto.getName())));
        supplier.setDisabled(dto.getDisabled());
        supplier.setName(dto.getName());
        supplier.setAddress(dto.getAddress());
        //保存供应商信息
        super.saveNonNull(supplier);
        return supplier.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void clientRemove(Long id) {
        Supplier supplier = super.getById(id);
        Optional.ofNullable(supplier).orElseThrow(()->new ServiceException("供应商信息不存在，请确认是否已经被删除"));
        PermissionUtil.checkClientCustomerPermission(supplier);
        //检查数据是否被银行信息和提货信息绑定
        this.remove(id);
    }

    @Override
    public PageInfo<Supplier> pageList(ClientSupplierQTO qto) {
        TsfWeekendSqls sqls = TsfWeekendSqls.<Supplier>custom()
                .andEqualTo(false,Supplier::getCustomerId,SecurityUtil.getCurrentCustomerId())
                .andEqualTo(true,Supplier::getDisabled,qto.getDisabled());
        return super.pageList(qto.getPage(),qto.getLimit(),sqls,Lists.newArrayList(OrderItem.asc("disabled"),OrderItem.desc("dateUpdated")));
    }

    @Override
    public SupplierVO get(Long id) {
        Supplier supplier = super.getById(id);
        Optional.ofNullable(supplier).orElseThrow(()->new ServiceException("供应商信息不存在，请确认是否已经被删除"));
        PermissionUtil.checkClientCustomerPermission(supplier);
        return beanMapper.map(supplier,SupplierVO.class);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void clientEdit(ClientSupplierDTO dto) {
        //校验供应商信息是否存在
        Supplier supplier = super.getById(dto.getId());
        TsfPreconditions.checkArgument(Objects.nonNull(supplier),new ServiceException("供应商信息不存在"));
        PermissionUtil.checkClientCustomerPermission(supplier);
        //校验该客户是否存在同名的供应商
        supplier.setName(StringUtils.removeSpecialSymbol(dto.getName()));

        int count = supplierMapper.selectCountByExample(Example.builder(Supplier.class).where(WeekendSqls.<Supplier>custom()
                .andEqualTo(Supplier::getCustomerId, SecurityUtil.getCurrentCustomerId())
                .andEqualTo(Supplier::getName,supplier.getName())
                .andNotEqualTo(Supplier::getId,supplier.getId())).build());
        TsfPreconditions.checkArgument(count < 1,new ServiceException(String.format("已经存在名称为：%s  的供应商",supplier.getName())));
        supplier.setCustomerId(SecurityUtil.getCurrentCustomerId());
        supplier.setAddress(StringUtils.removeSpecialSymbol(dto.getAddress()));
        supplier.setDisabled(dto.getDisabled());
        super.updateById(supplier);
    }
}
